package com.southminority.ethnic.service.heritage.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.southminority.ethnic.common.exception.BusinessException;
import com.southminority.ethnic.common.result.PageResult;
import com.southminority.ethnic.mapper.heritage.HeritageResearchLinkMapper;
import com.southminority.ethnic.pojo.HeritageResearchLink;
import com.southminority.ethnic.service.heritage.HeritageResearchLinkService;
import com.southminority.ethnic.controller.heritage.vo.HeritageResearchLinkVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 非遗-研究成果关联服务实现类.
 * 
 * @author SouthMinority
 */
@Slf4j
@Service
public class HeritageResearchLinkServiceImpl implements HeritageResearchLinkService {

    private final HeritageResearchLinkMapper researchLinkMapper;

    public HeritageResearchLinkServiceImpl(HeritageResearchLinkMapper researchLinkMapper) {
        this.researchLinkMapper = researchLinkMapper;
    }

    @Override
    public List<HeritageResearchLinkVO> getResearchLinksByHeritageId(Long heritageId) {
        if (heritageId == null) {
            return List.of(); // 返回空列表而不是null，避免空指针
        }
        
        // 调用自定义Mapper方法查询
        List<HeritageResearchLink> links = researchLinkMapper.selectByHeritageId(heritageId);
        return links.stream()
                   .map(this::convertToVO)
                   .collect(Collectors.toList());
    }

    @Override
    public PageResult<HeritageResearchLinkVO> getResearchLinkPageForAdmin(Integer page, Integer size, 
                                                                         Long heritageId, String keyword, String type, Integer status) {
        log.info("[ResearchLink][Page] page={}, size={}, heritageId={}, keyword={}, type={}, status={}", page, size, heritageId, keyword, type, status);
        Page<HeritageResearchLink> pageObj = new Page<>(page, size);
        QueryWrapper<HeritageResearchLink> wrapper = new QueryWrapper<>();
        
        // 动态构建筛选条件
        if (heritageId != null) {
            wrapper.eq("heritage_id", heritageId);
        }
        if (StringUtils.hasText(type)) {
            wrapper.eq("type", type);
        }
        if (status != null) {
            wrapper.eq("status", status);
        }
        if (StringUtils.hasText(keyword)) {
            wrapper.and(qw -> qw.like("title", keyword)
                               .or().like("description", keyword));
        }
        
        // 默认不显示已删除的
        wrapper.ne("status", -1);
        wrapper.orderByDesc("create_time");
        
        IPage<HeritageResearchLink> pageResult = researchLinkMapper.selectPage(pageObj, wrapper);
        log.info("[ResearchLink][Page] dbTotal={}, dbRecords={}", pageResult.getTotal(), pageResult.getRecords() != null ? pageResult.getRecords().size() : 0);
        
        // 封装分页结果
        List<HeritageResearchLinkVO> voList = pageResult.getRecords().stream()
                                                       .map(this::convertToVO)
                                                       .collect(Collectors.toList());
        
        return PageResult.<HeritageResearchLinkVO>builder()
                .current(pageResult.getCurrent())
                .size(pageResult.getSize())
                .total(pageResult.getTotal())
                .pages(pageResult.getPages())
                .records(voList)
                .build();
    }

    @Override
    public HeritageResearchLinkVO getResearchLinkDetail(Long id) {
        HeritageResearchLink link = researchLinkMapper.selectById(id);
        if (link == null) {
            throw new BusinessException("研究成果链接不存在");
        }
        
        return convertToVO(link);
    }

    @Override
    @Transactional
    public HeritageResearchLinkVO createResearchLink(HeritageResearchLink researchLink) {
        if (researchLink == null) {
            throw new BusinessException("研究成果信息不能为空");
        }
        log.info("[ResearchLink][Create] payload={}", researchLink);
        
        // 设置默认值
        if (researchLink.getStatus() == null) researchLink.setStatus(1);
        if (researchLink.getSortOrder() == null) researchLink.setSortOrder(0);
        
        int result = researchLinkMapper.insert(researchLink);
        log.info("[ResearchLink][Create] affectedRows={}, newId={}", result, researchLink.getId());
        if (result <= 0) {
            throw new BusinessException("创建研究成果链接失败");
        }
        
        return convertToVO(researchLink);
    }

    @Override
    @Transactional
    public HeritageResearchLinkVO updateResearchLink(Long id, HeritageResearchLink researchLink) {
        if (id == null || researchLink == null) {
            throw new BusinessException("参数不能为空");
        }
        log.info("[ResearchLink][Update] id={}, payload={}", id, researchLink);
        HeritageResearchLink existingLink = researchLinkMapper.selectById(id);
        if (existingLink == null) {
            throw new BusinessException("研究成果链接不存在");
        }
        log.info("[ResearchLink][Update] beforeDB={}", existingLink);
        // 使用 UpdateWrapper 精准更新非空字段，避免 BeanUtils 的边界问题
        LocalDateTime now = LocalDateTime.now();
        UpdateWrapper<HeritageResearchLink> uw = new UpdateWrapper<>();
        uw.eq("id", id);
        if (researchLink.getHeritageId() != null) uw.set("heritage_id", researchLink.getHeritageId());
        if (researchLink.getTitle() != null) uw.set("title", researchLink.getTitle());
        if (researchLink.getDescription() != null) uw.set("description", researchLink.getDescription());
        if (researchLink.getType() != null) uw.set("type", researchLink.getType());
        if (researchLink.getUrl() != null) uw.set("url", researchLink.getUrl());
        if (researchLink.getSourceTable() != null) uw.set("source_table", researchLink.getSourceTable());
        if (researchLink.getSourceId() != null) uw.set("source_id", researchLink.getSourceId());
        if (researchLink.getDate() != null) uw.set("date", researchLink.getDate());
        if (researchLink.getSortOrder() != null) uw.set("sort_order", researchLink.getSortOrder());
        if (researchLink.getStatus() != null) uw.set("status", researchLink.getStatus());
        uw.set("update_time", now);

        int result = researchLinkMapper.update(null, uw);
        log.info("[ResearchLink][Update] affectedRows={}", result);
        if (result <= 0) {
            throw new BusinessException("更新研究成果链接失败");
        }
        HeritageResearchLink after = researchLinkMapper.selectById(id);
        log.info("[ResearchLink][Update] afterDB={}", after);
        return convertToVO(after);
    }

    @Override
    @Transactional
    public Boolean deleteResearchLink(Long id) {
        if (id == null) {
            throw new BusinessException("研究成果链接ID不能为空");
        }
        
        HeritageResearchLink link = researchLinkMapper.selectById(id);
        if (link == null) {
            throw new BusinessException("研究成果链接不存在");
        }
        
        // 逻辑删除
        link.setStatus(-1);
        link.setUpdateTime(LocalDateTime.now());
        
        int result = researchLinkMapper.updateById(link);
        return result > 0;
    }

    @Override
    @Transactional
    public Boolean batchDeleteResearchLink(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new BusinessException("删除的研究成果链接ID列表不能为空");
        }
        
        List<HeritageResearchLink> linkList = researchLinkMapper.selectBatchIds(ids);
        if (linkList.isEmpty()) {
            return true; // 如果ID都无效，也认为成功
        }
        
        LocalDateTime now = LocalDateTime.now();
        for (HeritageResearchLink link : linkList) {
            link.setStatus(-1);
            link.setUpdateTime(now);
            researchLinkMapper.updateById(link);
        }
        
        return true;
    }

    @Override
    @Transactional
    public Boolean updateResearchLinkStatus(Long id, Integer status) {
        if (id == null || status == null) {
            throw new BusinessException("参数不能为空");
        }
        
        HeritageResearchLink link = researchLinkMapper.selectById(id);
        if (link == null) {
            throw new BusinessException("研究成果链接不存在");
        }
        
        link.setStatus(status);
        link.setUpdateTime(LocalDateTime.now());
        
        int result = researchLinkMapper.updateById(link);
        return result > 0;
    }

    /**
     * 将 HeritageResearchLink POJO 转换为 HeritageResearchLinkVO DTO.
     * <p>
     * 这是一个简单的属性复制转换，因为两个对象的字段基本一致。
     *
     * @param link 数据库实体对象
     * @return 用于前端展示的视图对象
     */
    private HeritageResearchLinkVO convertToVO(HeritageResearchLink link) {
        if (link == null) return null;
        HeritageResearchLinkVO vo = new HeritageResearchLinkVO();
        BeanUtils.copyProperties(link, vo);
        return vo;
    }

    /**
     * 将src中非空属性复制到target，空值属性不覆盖。
     */
    private static void copyNonNullProperties(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    /**
     * 获取对象中为null的属性名数组，供BeanUtils忽略这些字段。
     */
    private static String[] getNullPropertyNames(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();
        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        return emptyNames.toArray(new String[0]);
    }
} 